gusucode.com > VC Outlook风格的数据库浏览器 > VC Outlook风格的数据库浏览器/gusucode/Outlook/mdbViewerView.cpp

    //Download by http://www.NewXing.com
// mdbViewerView.cpp : implementation of the CmdbViewerView class
//

#include "stdafx.h"
#include "mdbViewer.h"

#include "mdbViewerDoc.h"
#include "mdbViewerView.h"
#include "MainFrm.h"
#include "RecordEditorDlg.h"
#include "QueryDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CmdbViewerView

IMPLEMENT_DYNCREATE(CmdbViewerView, CCJListView)

BEGIN_MESSAGE_MAP(CmdbViewerView, CCJListView)
	//{{AFX_MSG_MAP(CmdbViewerView)
	ON_WM_CONTEXTMENU()
	ON_WM_KEYUP()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_MOUSEMOVE()
	ON_WM_CANCELMODE()
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, OnFilePrintPreview)
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CCJListView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CCJListView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CCJListView::OnFilePrintPreview)
	ON_UPDATE_COMMAND_UI(ID_LISTVIEWROW_NUM,OnUpdateListRowNum)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CmdbViewerView construction/destruction

CmdbViewerView::CmdbViewerView()
{
	m_nColsmax = 0;			// max. number of columns
	m_nCurrentItemIndex=0;	// no item by default
	m_nRecords=0;			// no record
	m_IsQuery=FALSE;
	m_selectedRecords.SetSize(1);
	m_selectedRecords.SetAt(0,0);

}

CmdbViewerView::~CmdbViewerView()
{
}

BOOL CmdbViewerView::PreCreateWindow(CREATESTRUCT& cs)
{
	// default is report view
	cs.style |= LVS_REPORT;
	return CCJListView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CmdbViewerView drawing

void CmdbViewerView::OnDraw(CDC* pDC)
{
	CmdbViewerDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	pDC->TextOut(100,200,"here");
}

static UINT nImages[] =
{
	IDI_ICON_RECORD,
	IDI_ICON_RECORDSEL

};

void CmdbViewerView::OnInitialUpdate()
{
	CCJListView::OnInitialUpdate();

	// TODO: You may populate your ListView with items by directly accessing
	//  its list control through a call to GetListCtrl().
	m_pListCtrl = &GetListCtrl();

	// Create the large and small image lists
	m_ImageList.Create (16, 16, true, 2, 1);
	m_ImageListNormal.Create (32, 32, true, 2, 1);
	HICON hIcon;
	
	for (int i =0; i < 2; ++i) {
		hIcon= AfxGetApp()->LoadIcon (nImages[i]);
		m_ImageList.Add (hIcon);
		m_ImageListNormal.Add (hIcon);
	}

	m_pListCtrl->SetImageList (&m_ImageList, LVSIL_SMALL);
	m_pListCtrl->SetImageList (&m_ImageListNormal, LVSIL_NORMAL);
	m_pListCtrl->SetTextColor (RGB(0,0,255));

	m_Font.CreatePointFont (85, _T("Tahoma"));
    m_pListCtrl->SetFont (&m_Font);
	
	m_pListCtrl->SetExtendedStyle(LVS_EX_FULLROWSELECT | 
				 LVS_EX_ONECLICKACTIVATE | 
				 LVS_EX_UNDERLINEHOT | 
				 LVS_EX_GRIDLINES);
	
	m_headerCtrl.m_bBoldFont = FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// CmdbViewerView printing

BOOL CmdbViewerView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CmdbViewerView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CmdbViewerView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CmdbViewerView diagnostics

#ifdef _DEBUG
void CmdbViewerView::AssertValid() const
{
	CCJListView::AssertValid();
}

void CmdbViewerView::Dump(CDumpContext& dc) const
{
	CCJListView::Dump(dc);
}

CmdbViewerDoc* CmdbViewerView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CmdbViewerDoc)));
	return (CmdbViewerDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CmdbViewerView message handlers

void CmdbViewerView::OnContextMenu(CWnd* pWnd, CPoint point) 
{
	// bring up POPup menu and set up its style.
	// The popup menu messages will be responsed in cMainFrame class
	if (point.x == -1 && point.y == -1){
		//keystroke invocation
		CRect rect;
		GetClientRect(rect);
		ClientToScreen(rect);
		
		point = rect.TopLeft();
		point.Offset(5, 5);
	}
	
	CMenu menu;
	VERIFY(menu.LoadMenu(IDR_POPUP));
	
	CMenu* pPopup = menu.GetSubMenu(0);
	ASSERT(pPopup != NULL);
	CWnd* pWndPopupOwner = this;
	
	while (pWndPopupOwner->GetStyle() & WS_CHILD)
		pWndPopupOwner = pWndPopupOwner->GetParent();
	
	pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
		pWndPopupOwner);
}


void CmdbViewerView::ClearListView()
{
	if(m_pListCtrl!=NULL) ASSERT(m_pListCtrl);
	m_pListCtrl->DeleteAllItems();
}

void CmdbViewerView::ShowDBTable()
{
	ProcessUpdating(_T("Loading recordset ..."));
	// suppose a record set has been opened
	CmdbViewerDoc* pDoc = GetDocument();
	if(m_pListCtrl!=NULL) ClearListView();
	pDoc->LoadRecordset();
	// After call for pDoc->LoadRecordset,
	// the pDoc->m_pRecordset is renewed
	// and therefore you must update your local variables associated
	// with pDoc->m_pRecordset, for example m_pSet.
	m_pSet=pDoc->GetRecordSet();
	m_TableName=pDoc->GetTableName();
	ProcessUpdating(_T("Updating list view  ..."));
	if(m_pSet!= NULL)
	{
		ASSERT_VALID(m_pSet);
		BeginWaitCursor();
		m_nFields = (int) m_pSet->GetFieldCount();
		int nColSize =80;
		CString fieldname;
		CDaoFieldInfo fi;

		// build columns first
		LV_COLUMN lvCol;
		lvCol.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
        lvCol.cx = nColSize;
		lvCol.fmt = LVCFMT_LEFT;

        for(int i = 0; i < m_nFields; i++) {
            m_pSet->GetFieldInfo(i, fi);
			fieldname=fi.m_strName;
			// Insert the ith column into the list control
			lvCol.iSubItem = i;
			lvCol.pszText = (char*)(LPCTSTR)fieldname;
			if(i<m_nColsmax)
			{
				m_pListCtrl->SetColumn(i, &lvCol);
			} else m_pListCtrl->InsertColumn(i, &lvCol);
		}
       	if(m_nColsmax-m_nFields>0) {
			for(i = m_nFields; i <m_nColsmax; i++) {
				lvCol.iSubItem = i;
				lvCol.pszText = (char*)(LPCTSTR)(_T(""));
				lvCol.cx = 0; // set this column width as 0 
				m_pListCtrl->SetColumn(i, &lvCol);				
			}
		}
					
		if(m_nColsmax<m_nFields) m_nColsmax=m_nFields;

		// insert items
		
		LV_ITEM		lvi;
		lvi.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_STATE;
		lvi.stateMask = LVIS_STATEIMAGEMASK;
		lvi.state = INDEXTOSTATEIMAGEMASK(1);
		lvi.iSubItem = 0;
		lvi.iImage = 0;  // use icon IDI_ICON_RECORD
		COleVariant var;
		CString str;
		for (int j=0;! m_pSet->IsEOF () ;j++) {
					lvi.iItem = j;
					
                    var = m_pSet->GetFieldValue(0);
					str=formatedValue(var);
					lvi.pszText = (char*)(LPCTSTR)str;
					if (m_pListCtrl->InsertItem(&lvi) != -1) {
						for(i = 1; i < m_nFields; i++) {
							var = m_pSet->GetFieldValue(i);
							str=formatedValue(var);
							m_pListCtrl->SetItemText(j, i, str);
						}	// loop on column index i
					}
									
			m_pSet->MoveNext();
		}			// loop on row index j
		EndWaitCursor();
		// When loading finished, m_pSet points to the last record, which can
		// be used to validate the record count
		m_pSet->MoveLast();
		m_nRecords=m_pSet->GetAbsolutePosition()+1;

	} else {
		AfxMessageBox(_T("This recordset is not properly opened"));
		return;
	}

	m_IsQuery=FALSE;

}

CString CmdbViewerView::formatedValue(COleVariant var)
{
	CString str;
	switch (var.vt) {
	  case VT_BSTR:
		str = (LPCSTR) var.bstrVal; // narrow characters in DAO
		break;
	  case VT_I2:
		str.Format("%d", (int) var.iVal);
		break;
	  case VT_I4:
		str.Format("%d", var.lVal);
		break;
	  case VT_R4:
		str.Format("%10.2f", (double) var.fltVal);
		break;
	  case VT_R8:
		str.Format("%10.2f", var.dblVal);
		break;
	  case VT_CY:
		str = COleCurrency(var).Format();
		break;
	  case VT_DATE:
		str = COleDateTime(var).Format();
		break;
	  case VT_BOOL:
		str = (var.boolVal == 0) ? "FALSE" : "TRUE";
		break;
	  case VT_NULL:
		str =  "----";
		break;
	  default:
		str.Format("Unk type %d\n", var.vt);
		TRACE("Unknown type %d\n", var.vt);
	  }
	return str;
}


void CmdbViewerView::OnUpdateListRowNum(CCmdUI* pCmdUI)
{
	CString strRowInfo;

	strRowInfo.Format(_T("Record: %d of %d"), m_nCurrentItemIndex+1, m_nRecords);
	pCmdUI->SetText(strRowInfo);
}

void CmdbViewerView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	// Because the GetSelectedItemIndex() is used, this method
	// also functions for KeyDown, Home, End,PageUp,PageDown
	// The benefit of this is we do not need to catch all the messages
	// while a reasonable speed is reserved.
	SetSelectedItemIndex();
	CCJListView::OnKeyUp(nChar, nRepCnt, nFlags);
}

void CmdbViewerView::SetSelectedItemIndex()
{
	m_pListCtrl = &GetListCtrl();
	ASSERT(m_pListCtrl != NULL);
	POSITION pos = m_pListCtrl->GetFirstSelectedItemPosition();
	if (pos == NULL) {
			TRACE0("No items were selected!\n");
	} else {
		m_nCurrentItemIndex=m_pListCtrl->GetNextSelectedItem(pos);
	}
	if(m_IsQuery&&(m_nCurrentItemIndex>=0)&&(m_nCurrentItemIndex<=m_selectedRecords.GetUpperBound()))
		m_nCurrentItemIndex=m_selectedRecords.GetAt(m_nCurrentItemIndex);
}


void CmdbViewerView::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	// Navigate from here
	Navigation();
	CCJListView::OnLButtonDblClk(nFlags, point);
}


BOOL CmdbViewerView::UpdateListView(int nFlag, CStringArray *fieldValues)
{
	// nFlag=1 add an item at last
	// nFlag=2 modify an item at current position
	// nFlag=3 delete an item at current position

	CmdbViewerDoc* pDoc = GetDocument();
	m_pSet=pDoc->GetRecordSet();

	m_pListCtrl = &GetListCtrl();

	if(nFlag==1) {
		// to validate record count
		if (!m_pSet->IsBOF()) {
			m_pSet->MoveLast();
		}
	}
	int nRowIdx=m_pSet->GetAbsolutePosition();
	AfxMessageBox(pDoc->IntoStr(nRowIdx));
	/*
	if((nFlag==3)&&(nRowIdx>=0)) {
		// delete the current item from the 
		m_pListCtrl->DeleteItem(nRowIdx);
		return TRUE;
	}
	*/
	if((nFlag==3)&&(m_nCurrentItemIndex>=0)) {
		// delete the current item from the 
		m_pListCtrl->DeleteItem(m_nCurrentItemIndex);
		return TRUE;
	}
	
	LV_ITEM		lvi;
	lvi.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_STATE;
	lvi.iItem = nRowIdx;
	lvi.iSubItem = 0;
	lvi.iImage = NULL;  // use icon IDI_ICON_OUTLOOK
	lvi.stateMask = LVIS_STATEIMAGEMASK;
	lvi.state = INDEXTOSTATEIMAGEMASK(1);
	lvi.pszText = (char*)(LPCTSTR)(fieldValues->GetAt(0));
	if (m_pListCtrl->InsertItem(&lvi) != -1) {
		for(int i = 1; i < m_nFields; i++) {
			m_pListCtrl->SetItemText(nRowIdx, i, fieldValues->GetAt(i));
		}	// loop on column index i
		m_pListCtrl->Update(nRowIdx);
		return TRUE;
	} else return FALSE;
}

void CmdbViewerView::OnMouseMove(UINT nFlags, CPoint point) 
{
	m_pListCtrl = &GetListCtrl();
	ASSERT(m_pListCtrl != NULL);
	if(m_pListCtrl->GetItemCount()==0) {
		return; // No record in the recordset
	}
	m_nCurrentItemIndex=m_pListCtrl->HitTest(point);

	if(m_IsQuery&&(m_nCurrentItemIndex>=0)&&(m_nCurrentItemIndex<=m_selectedRecords.GetUpperBound()))
		m_nCurrentItemIndex=m_selectedRecords.GetAt(m_nCurrentItemIndex);
	
	CCJListView::OnMouseMove(nFlags, point);
}

void CmdbViewerView::OnCancelMode() 
{
	CCJListView::OnCancelMode();
	
	// TODO: Add your message handler code here
	
}


void CmdbViewerView::Navigation()
{
	if(m_IsQuery) return;  // no navigation if the list view is at query state

	m_pListCtrl = &GetListCtrl();
	ASSERT(m_pListCtrl != NULL);

	if(m_pListCtrl->GetItemCount()==0) {
		return; // No record in the recordset
		// One thing could be done is to add a new record
		// You can implement this
	}
	
	if(m_nRecords>0) {
		CmdbViewerDoc* pDoc = GetDocument();
		m_pSet=pDoc->GetRecordSet();
		if(m_nCurrentItemIndex<0) m_nCurrentItemIndex=0;
		m_pSet->SetAbsolutePosition(m_nCurrentItemIndex); // point to current record
				
		CRecordEditorDlg* REDdlg=new CRecordEditorDlg(this);
		CStringArray fieldValues;
		CStringArray fieldNames;
		fieldValues.SetSize(40);
		fieldNames.SetSize(40);
		for (int i=0;i<40;i++) {
			fieldValues[i]=_T("");
			fieldNames[i]=_T("");
		}

		COleVariant var;
		CDaoFieldInfo fi;
		for (i = 0; i < m_nFields; i++) {
			  var = m_pSet->GetFieldValue(i);
			  m_pSet->GetFieldInfo(i, fi);
			  fieldNames[i] = fi.m_strName;
			  fieldValues[i]=formatedValue(var);
		} // Loop on i

		REDdlg->m_fieldValue1 = fieldValues.GetAt(0);
		REDdlg->m_fieldValue2 = fieldValues.GetAt(1);
		REDdlg->m_fieldValue3 = fieldValues.GetAt(2);
		REDdlg->m_fieldValue4 = fieldValues.GetAt(3);
		REDdlg->m_fieldValue5 = fieldValues.GetAt(4);
		REDdlg->m_fieldValue6 = fieldValues.GetAt(5);
		REDdlg->m_fieldValue7 = fieldValues.GetAt(6);
		REDdlg->m_fieldValue8 = fieldValues.GetAt(7);
		REDdlg->m_fieldName1 = fieldNames.GetAt(0);
		REDdlg->m_fieldName2 = fieldNames.GetAt(1);
		REDdlg->m_fieldName3 = fieldNames.GetAt(2);
		REDdlg->m_fieldName4 = fieldNames.GetAt(3);
		REDdlg->m_fieldName5 = fieldNames.GetAt(4);
		REDdlg->m_fieldName6 = fieldNames.GetAt(5);
		REDdlg->m_fieldName7 = fieldNames.GetAt(6);
		REDdlg->m_fieldName8 = fieldNames.GetAt(7);
	
		for (i=0;i<m_nFields; i++) {
			REDdlg->PassFieldNames(i,fieldNames[i]);
			REDdlg->PassFieldValues(i,fieldValues[i]);
		}

		m_pSet->SetAbsolutePosition(m_nCurrentItemIndex); // point to current record

		if(REDdlg->DoModal()==IDOK)
		{
			//
		}
		
	} // if not the title row
}

void CmdbViewerView::Enquery()
{
	m_pListCtrl = &GetListCtrl();
	ASSERT(m_pListCtrl != NULL);
	if(m_pListCtrl->GetItemCount()==0) {
		return; 
	}
 	if(m_nRecords>0) {
		CmdbViewerDoc* pDoc = GetDocument();
		if(m_nCurrentItemIndex<0) m_nCurrentItemIndex=0;
		m_pSet=pDoc->GetRecordSet();
		CQueryDlg* Qdlg=new CQueryDlg(this);
		
		if(Qdlg->DoModal()==IDOK)
		{
			BeginWaitCursor();
			m_queryString=Qdlg->m_queryString;
			m_queryField=Qdlg->GetqueryFieldName();
			ExecuteQuery();
			EndWaitCursor();
			CMainFrame* pFrame=(CMainFrame*) AfxGetApp()->m_pMainWnd;
			CString str;
			str.Format(_T("Query : [%s]  %s"), m_queryField, m_queryString);
			pFrame->AddNewQuery(str);

		}
	} // if not the title row
}

void CmdbViewerView::ExecuteQuery()
{
	if(m_queryString.IsEmpty()) {
		m_IsQuery=FALSE;
		return;
	} else 	m_IsQuery=TRUE;
	ProcessUpdating(_T("Loading recordset ..."));
	// suppose a record set has been opened
	CmdbViewerDoc* pDoc = GetDocument();
	if(m_pListCtrl!=NULL) ClearListView();
	pDoc->LoadRecordset();
	m_pSet=pDoc->GetRecordSet();
	m_TableName=pDoc->GetTableName();
	ProcessUpdating(_T("Searching and updating list view  ..."));
	int queryFieldIndex=0;
	if(m_pSet!= NULL)
	{
		ASSERT_VALID(m_pSet);
		m_nFields = (int) m_pSet->GetFieldCount();
		int nColSize =80;
		CString fieldname;
		CDaoFieldInfo fi;

		// build columns first
		LV_COLUMN lvCol;
		lvCol.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
        lvCol.cx = nColSize;
		lvCol.fmt = LVCFMT_LEFT;

        for(int i = 0; i < m_nFields; i++) {
            m_pSet->GetFieldInfo(i, fi);
			fieldname=fi.m_strName;
			if(fieldname.Compare(m_queryField)==0) queryFieldIndex=i;
			// Insert the ith column into the list control
			lvCol.iSubItem = i;
			lvCol.pszText = (char*)(LPCTSTR)fieldname;
			if(i<m_nColsmax)
			{
				m_pListCtrl->SetColumn(i, &lvCol);
			} else m_pListCtrl->InsertColumn(i, &lvCol);
		}
       	if(m_nColsmax-m_nFields>0) {
			for(i = m_nFields; i <m_nColsmax; i++) {
				lvCol.iSubItem = i;
				lvCol.pszText = (char*)(LPCTSTR)(_T(""));
				lvCol.cx = 0; // set this column width as 0 
				m_pListCtrl->SetColumn(i, &lvCol);				
			}
		}
					
		if(m_nColsmax<m_nFields) m_nColsmax=m_nFields;

		// insert items
		
		LV_ITEM		lvi;
		lvi.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_STATE;
		lvi.stateMask = LVIS_STATEIMAGEMASK;
		lvi.state = INDEXTOSTATEIMAGEMASK(1);
		lvi.iSubItem = 0;
		lvi.iImage = 1;  // use icon IDI_ICON_RECORDSEL
		COleVariant var;
		CString str,str1,str2;
		int selectedItems=0;
		for (int j=0;! m_pSet->IsEOF () ;j++) {
			var = m_pSet->GetFieldValue(queryFieldIndex);
			str1=formatedValue(var);
			str1.MakeLower();
			str2=m_queryString;
			str2.MakeLower();
			
			if(str1.Find(str2)>=0) {
					lvi.iItem = selectedItems;
					var = m_pSet->GetFieldValue(0);
					str=formatedValue(var);
					lvi.pszText = (char*)(LPCTSTR)str;
					if (m_pListCtrl->InsertItem(&lvi) != -1) {
						for(i = 1; i < m_nFields; i++) {
							var = m_pSet->GetFieldValue(i);
							str=formatedValue(var);
							m_pListCtrl->SetItemText(selectedItems, i, str);
						}	// loop on column index i
					}
					if(m_IsQuery) m_selectedRecords.SetAtGrow(selectedItems,j);
					selectedItems++;
			}
			m_pSet->MoveNext();
		}			// loop on row index j
		m_selectedRecords.FreeExtra();
		
	} else {
		AfxMessageBox(_T("This recordset is not properly opened"));
		return;
	}


}

void CmdbViewerView::ProcessUpdating(CString strProcess)
{
	CMainFrame* pFrame=(CMainFrame*) AfxGetApp()->m_pMainWnd;
	CStatusBar* pStatus=&pFrame->m_wndStatusBar;
	if(pStatus) {
		pStatus->SetPaneText(pStatus->CommandToIndex(ID_LISTVIEWROW_NUM),strProcess);
	}
}

void CmdbViewerView::OnFilePrintPreview() 
{
	// TODO: Add your command handler code here
	
}